package com.qing.common.utils.json.hutool;

import cn.hutool.core.annotation.Alias;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.CharUtil;
import cn.hutool.core.util.ModifierUtil;
import cn.hutool.json.JSONUtil;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author guoqf
 */
public class HutoolJsonUtil {
    public static void main(String[] args) {
//        testJson();


//        testMethodMap();

//        testContinuousChars();

//        testKeyboardContinuousChars();

//        testKeyboardContinuousMatch(getCharacterMap());

        String applyReason="我们都有一个家";
        validateGoldBankApprovalApplyReasonCnCount(applyReason, "4");
        System.out.println("============================");
        applyReason = "我我我我我我我我我我我我我";
        validateGoldBankApprovalApplyReasonCnCount(applyReason, "4");
        System.out.println("============================");

        applyReason = "我是谁，谁是我";
        validateGoldBankApprovalApplyReasonCnCount(applyReason, "4");
        System.out.println("============================");

    }

    private static void testKeyboardContinuousChars() {
        Map<Character, int[]> indexMap = getCharacterMap();

        indexMap.forEach((k, v) -> {
            System.out.println("char=" + k + ", indexX=" + v[0] + ", indexY=" + v[1]);
        });

        System.out.println("indexedMap: " + indexMap.size());
    }

    private static void testKeyboardContinuousMatch(Map<Character, int[]> keyboardIndexMap) {
        String[] s1 = {"aedfxsi;amva", "assdfghj", "123456789", "90-="};
        for (String s : s1) {
            validateKeyboardContinuous(keyboardIndexMap, s);
        }


    }

    private static boolean validateGoldBankApprovalApplyReasonCnCount(String applyReason, String requiredCount) {
        int setCnCount = 0;
        if (StringUtils.isEmpty(requiredCount)) {
            setCnCount = 4;
        } else {
            try {
                setCnCount = Integer.parseInt(requiredCount.trim());
            } catch (NumberFormatException e) {
                e.printStackTrace();
            }
            if (setCnCount < 4 || setCnCount > 10) {
                setCnCount = 4;
            }
        }
        String regEx = "[\\u4e00-\\u9fa5]";
        Pattern p = Pattern.compile(regEx);
        Matcher m = p.matcher(applyReason);

        int groupCount = m.groupCount();
        Set<String> cnCount = new HashSet<>();

        while (m.find()) {
            for (int i = 0; i <= m.groupCount(); i++) {
                String group = m.group();
                System.out.println(group);
                cnCount.add(group);
            }
        }

        System.out.println(applyReason + "：不同中文个数: " + cnCount.size());
        System.out.println(cnCount);
        return groupCount >= setCnCount;

    }

    private static void validateKeyboardContinuous(Map<Character, int[]> keyboardIndexMap, String s) {
        System.out.println("test string: " + s);
        char[] chars = s.toCharArray();
        boolean hasContinuous = false;
        for (int i = 0; i < chars.length - 2; i++) {
            char aChar = chars[i];
            int[] firstIndexes = keyboardIndexMap.get(aChar);
            char bChar = chars[i + 1];
            int[] secondIndexes = keyboardIndexMap.get(bChar);
            char cChar = chars[i + 2];
            int[] thirdIndexes = keyboardIndexMap.get(cChar);
            if (ArrayUtil.isAllNotNull(firstIndexes, secondIndexes, thirdIndexes)) {
                int firstX = firstIndexes[0];
                int secondX = secondIndexes[0];
                int thirdX = thirdIndexes[0];
                int firstY = firstIndexes[1];
                int secondY = secondIndexes[1];
                int thirdY = thirdIndexes[1];
                boolean continuousX = firstX == secondX && secondX == thirdX && firstY + 1 == secondY && secondY + 1 == thirdY;
                boolean continuousY = firstY == secondY && secondY == thirdY && firstX + 1 == secondX && secondX + 1 == thirdX;

                boolean isContinuous = continuousX || continuousY;
                if (isContinuous && !isAllNumber(aChar, bChar, cChar)) {
                    hasContinuous = true;
                    break;
                }
            }
        }

        if (hasContinuous) {
            System.out.println(s + "存在键盘连续非数字");
        } else {
            System.out.println(s + "NOT存在键盘连续非数字");
        }
    }


    private static boolean isAllNumber(char... chars) {
        if (chars != null && chars.length > 0) {
            boolean allNumber = true;
            for (char c : chars) {
                if (!CharUtil.isNumber(c)) {
                    allNumber = false;
                    break;
                }
            }
            return allNumber;
        }
        return false;
    }

    private static Map<Character, int[]> getCharacterMap() {
        char[][] upperArray = {
                {'!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+'},
                {'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', '|'},
                {'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"'},
                {'Z', 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?'}
        };
        char[][] lowerArray = {
                {'1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '='},
                {'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\\'},
                {'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\''},
                {'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/'}
        };
        Map<Character, int[]> indexMap = new HashMap<>(128);
        for (int i = 0; i < upperArray.length; i++) {
            char[] chars1 = upperArray[i];
            char[] chars2 = lowerArray[i];
            for (int j = 0; j < chars1.length; j++) {
                int[] c = {i, j};
                indexMap.put(chars1[j], c);
                indexMap.put(chars2[j], c);
            }
        }
        return indexMap;
    }

    private static void testContinuousChars() {
        String s = "abcedf";

        char[] chars = s.toCharArray();
        for (int i = 1; i < chars.length - 1; i++) {

            System.out.println("====================");
            System.out.println("char[i]: " + chars[i] + ", char[i-1]: " + chars[i - 1] + ", char[i+1]: " + chars[i + 1]);
            System.out.println("char[i]-char[i-1]: " + (chars[i] - chars[i - 1]) + ", char[i+1]- char[i]: " + (chars[i + 1] - chars[i]));
            System.out.println("char[i]-char[i-1]==1?: " + (chars[i] - chars[i - 1] == 1) + ", char[i+1]- char[i]==1: " + (chars[i + 1] - chars[i] == 1));

            System.out.println("********************");

        }
    }

    private static void testMethodMap() {
        for (int i = 0; i < 50; i++) {

//            Map<Class<?>, Method> methodMap = getMethodMap(ConvertorEnum.class);
//            System.out.println("=============ParameterTypeMap" + i + ": " + methodMap);

            Method[] methods = ConvertorEnum.class.getMethods();
            System.out.println("=======Loop" + i);
            for (Method m : methods) {
                if (ModifierUtil.isStatic(m) && ModifierUtil.isPublic(m) && !m.getName().equals("values") && !m.getName().equals("valueOf")) {
                    System.out.println(m.getName());
                }
            }

        }

        Map<Class<?>, Method> methodMapByName = getMethodMapByName(ConvertorEnum.class);

        System.out.println("=============MethodNameMap: " + methodMapByName);
    }

    private static void testJson() {
        TestJson testJson = new TestJson();
        testJson.setId("111");
//        testJson.setName("zhangsan");
        testJson.setMyAddress("adfasdfasdf");
        testJson.setConvertorEnum(ConvertorEnum.VALUE1);

        String testStr = toJsonStr(testJson);
        System.out.println(testStr);


        String str = "{\"id\":\"111\",\"my_address\":\"adfasdfasdf\",\"convertorEnum\":\"MAIN_ACCT\"}";
        TestJson testJson1 = JSONUtil.toBean(str, TestJson.class);


        System.out.println(testJson1);
    }

    private static Map<Class<?>, Method> getMethodMap(Class<?> enumClass) {
        return new HashMap<Class<?>, Map<Class<?>, Method>>().computeIfAbsent(enumClass, (key) -> {
            return (Map) Arrays.stream(enumClass.getMethods()).filter(ModifierUtil::isStatic).filter((m) -> {
                return m.getReturnType() == enumClass;
            }).filter((m) -> {
                return m.getParameterCount() == 1;
            }).filter((m) -> {
                return !"valueOf".equals(m.getName());
            }).collect(Collectors.toMap((m) -> {
                return m.getParameterTypes()[0];
            }, (m) -> {
                return m;
            }, (k1, k2) -> {
                return k1;
            }));
        });
    }
    private static Map<Class<?>, Method> getMethodMapByName(Class<?> enumClass) {
        return new HashMap<Class<?>, Map<Class<?>, Method>>().computeIfAbsent(enumClass, (key) -> {
            return (Map) Arrays.stream(enumClass.getMethods()).filter(ModifierUtil::isStatic).filter((m) -> {
                return m.getReturnType() == enumClass;
            }).filter((m) -> {
                return m.getParameterCount() == 1;
            }).filter((m) -> {
                return !"valueOf".equals(m.getName());
            }).collect(Collectors.toMap((m) -> {
                return m.getName();
            }, (m) -> {
                return m;
            }, (k1, k2) -> {
                return k1;
            }));
        });
    }
    public static String toJsonStr(Object bean) {

        return JSONUtil.toJsonStr(bean);
    }


    @Data
    static class TestJson {
        private String id;

        private String name;

        @Alias("my_address")
        private String myAddress;

        private ConvertorEnum convertorEnum;

    }
}
